<template>
  <n-tree
    block-line
    expand-on-click
    :data="data"
    :default-expanded-keys="expandedKeys"
    :node-props="nodeProps"
    :on-update:expanded-keys="updatePrefixWithExpaned"
  />
</template>

<script setup lang="ts">
import { FileTreeEntries, FileTreeEntry } from '@/typings'
import { computed, h, ref } from 'vue'
import { fileExtParser } from '@/utils'
import { NIcon, type TreeOption } from 'naive-ui'
import { Folder, FolderOpenOutline, FileTrayFullOutline } from '@vicons/ionicons5'
import { DocumentUnknown } from '@vicons/carbon'
import getFileIcon from './getFileIcon'

interface Props {
  fileTreeEntries: FileTreeEntries
  // 是否显示后缀
  showExtension?: boolean
  // 树状结构展开的层数
  expandedLevel?: number
  // 未知格式的文件是否显示为文件夹(对叶子结点都为文件夹的情况非常有用)
  unknownAsFolder?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  showExtension: false,
  // 默认展开0层，只展示根元素
  expandedLevel: 0,
  unknownAsFolder: false,
})

const updatePrefixWithExpaned = (
  _keys: Array<string | number>,
  _option: Array<TreeOption | null>,
  meta: {
    node: TreeOption | null
    action: 'expand' | 'collapse' | 'filter'
  }
) => {
  if (!meta.node) return
  switch (meta.action) {
    case 'expand':
      meta.node.prefix = () =>
        h(NIcon, null, {
          default: () => h(FolderOpenOutline),
        })
      break
    case 'collapse':
      meta.node.prefix = () =>
        h(NIcon, null, {
          default: () => h(Folder),
        })
      break
  }
}

const emit = defineEmits<{
  (e: 'on-click-file', option: TreeOption): void
}>()
const nodeProps = ({ option }: { option: TreeOption }) => {
  return {
    onClick() {
      if ((!option.children || option.children.length == 0) && !option.disabled) {
        emit('on-click-file', option)
      }
    },
  }
}

const data = computed(() => props.fileTreeEntries.map((f) => convert(f, 1)))
const expandedKeys = ref<string[]>([])

function convert(fileTreeEntry: FileTreeEntry, currentLevel: number): TreeOption {
  const { key, name, isFolder, children, isLeaf, data } = fileTreeEntry
  let fileIcon = getFileIcon(name, isFolder)
  if (currentLevel <= props.expandedLevel) {
    expandedKeys.value.push(key)
    if (fileIcon === Folder) fileIcon = FolderOpenOutline
  }
  if (props.unknownAsFolder && fileIcon === DocumentUnknown) {
    fileIcon = Folder
  }
  const treeOption: TreeOption = {
    key,
    name,
    label: props.showExtension ? name : fileExtParser.removeExtension(name),
    disabled: false,
    isLeaf,
    data,
    prefix: () =>
      h(NIcon, null, {
        default: () => h(fileIcon),
      }),
    children: children.map((c) => convert(c, currentLevel + 1)),
  }
  return treeOption
}
</script>

<style scoped></style>
